package com.ryl.yomall.cart.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.ryl.yomall.cart.mapper.CartInfoMapper;
import com.ryl.yomall.cart.service.CartInfoService;
import com.ryl.yomall.model.cart.CartInfo;
import com.ryl.yomall.model.common.constant.RedisConst;
import com.ryl.yomall.model.common.util.AuthContextHolder;
import com.ryl.yomall.model.product.SkuInfo;
import com.ryl.yomall.product.client.ProductFeignClient;
import jodd.util.ThreadUtil;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;
import org.springframework.util.CollectionUtils;
import org.springframework.util.StringUtils;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;

import javax.servlet.http.HttpServletRequest;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

/**
 * @Date 13:20
 * @Author ryl
 */
@Service
public class CartInfoServiceImpl implements CartInfoService {
    @Autowired
    private CartInfoMapper cartInfoMapper;
    @Autowired
    private ProductFeignClient productFeignClient;
    @Autowired
    private RedisTemplate redisTemplate;
    public static final Integer isChecked =1;

    @Override
    public CartInfo addToCart(Long skuId ,Integer skuNum ,String userId) {

        //1:查询购物车列表
        //优先前 使用DB  select * from cart_info where user_id = 3 and sku_id = 1
       /* CartInfo cartInfo = cartInfoMapper.selectOne(new QueryWrapper<CartInfo> ()
                .eq("user_id", userId).eq("sku_id", skuId));*/
        //优先后  使用Redis  实时跟MysqlDB之间同步
        CartInfo cartInfo = (CartInfo) redisTemplate.opsForHash ( ).get ( RedisConst.USER_KEY_PREFIX +
                userId + RedisConst.USER_CART_KEY_SUFFIX ,skuId.toString ( ) );
        //2:判断是否为同款
        if (null != cartInfo) {
            //同款 合并数量
            cartInfo.setSkuNum ( cartInfo.getSkuNum ( ) + skuNum );
            //选中状态
            cartInfo.setIsChecked ( CartInfo.isCheckedOK );
            //更新
            cartInfoMapper.updateById ( cartInfo );//Canal 同步的Redis缓存中
        } else {
            //追加新款
            cartInfo = new CartInfo ( );
            //用户ID
            cartInfo.setUserId ( userId );
            //库存ID
            cartInfo.setSkuId ( skuId );
            //设置数量
            cartInfo.setSkuNum ( skuNum );
            //选中
            cartInfo.setIsChecked ( CartInfo.isCheckedOK );

            SkuInfo skuInfo = productFeignClient.getSkuInfo ( skuId );
            //价格 购物车加入时的价格
            cartInfo.setCartPrice ( skuInfo.getPrice ( ) );
            //  实时价格
            cartInfo.setSkuPrice ( skuInfo.getPrice ( ) );
            //标题
            cartInfo.setSkuName ( skuInfo.getSkuName ( ) );
            //图片
            cartInfo.setImgUrl ( skuInfo.getSkuDefaultImg ( ) );
            //保存新款
            cartInfoMapper.insert ( cartInfo );//同步Redis缓存
        }
        cartInfo.setSkuNum ( skuNum );
        return cartInfo;
    }

    @Override
    public List<CartInfo> cartList(String userId ,String userTempId) {
       //1. 用户是否登录了
        if(!StringUtils.isEmpty ( userId )){
            if(!StringUtils.isEmpty ( userTempId )){
                //合并
                return mergeCartInfoList(userId,userTempId);
            }else{
                //无临时用户
                 return getCartInfoList(userId);
            }
        }else{
           //未登录
            return getCartInfoList(userTempId);
        }


    }



    //合并
    public List<CartInfo> mergeCartInfoList(String userId ,String userTempId) {
        //获取购物车
        List<CartInfo> userIdCartInfoList = getCartInfoList(userId);
        List<CartInfo> userTempIdCartInfoList = getCartInfoList(userTempId);
        //1.判断真实用户是否有购物车
        if(!CollectionUtils.isEmpty ( userIdCartInfoList )){
           //有真实购物车
            //临时购物车是否存在
            if(! CollectionUtils.isEmpty ( userTempIdCartInfoList )){
                //真实有,临时有 ,就合并
                //将真实用户的购物车集合转换成map
                Map<Long, CartInfo> userIdCartMap = userIdCartInfoList.stream ( )
                        .collect ( Collectors.toMap ( CartInfo::getSkuId ,
                        cartInfo -> cartInfo ) );
                //将临时的购物车合并给真实的购物车
                userTempIdCartInfoList.forEach ( userTempIdCartInfo->{
                    //是否在真实的购物车已经存在
                    CartInfo userIdCartInfo = userIdCartMap.get ( userTempIdCartInfo.getSkuId ( ) );
                    if(userIdCartInfo !=null){
                        //--存在了就追加数量
                        userIdCartInfo.setSkuNum(userTempIdCartInfo.getSkuNum() +
                                userIdCartInfo.getSkuNum());
                        //更新真实用户对应的购物车数量
                        cartInfoMapper.updateById(userIdCartInfo);
                        //删除临时用户(相同款)
                        cartInfoMapper.deleteById ( userTempIdCartInfo.getId () );
                    }else{
                        //不存在 就添加新款
                        userIdCartMap.put ( userTempIdCartInfo.getSkuId (), userTempIdCartInfo);
                        //更新用户车的用户id 为真实id
                        userTempIdCartInfo.setUserId ( userId );
                        cartInfoMapper.updateById ( userTempIdCartInfo );
                    }
                } );
                //清理临时用户的缓存
                redisTemplate.delete ( RedisConst.USER_KEY_PREFIX +
                        userTempId + RedisConst.USER_CART_KEY_SUFFIX );
                return new ArrayList<> ( userIdCartMap.values () );

            }else{
                return userIdCartInfoList;
            }
        }else{
            //无真实购物车
            //更新cart_info user_id 改成真实用户的
            CartInfo cartInfo = new CartInfo ();
            cartInfo.setUserId ( userId );
            cartInfoMapper.update ( cartInfo,new QueryWrapper<CartInfo> ( ).eq ( "user_id", userTempId) );
            //清理临时用户的缓存
            redisTemplate.delete ( RedisConst.USER_KEY_PREFIX +
                    userTempId + RedisConst.USER_CART_KEY_SUFFIX );
            return userTempIdCartInfoList;
        }

    }

    //查询当前用户购物车集合
    public List<CartInfo> getCartInfoList(String userId){

        //1.先从缓存中查询
        List<CartInfo> cartInfoList = redisTemplate.opsForHash ( ).values ( RedisConst.USER_KEY_PREFIX + userId
                + RedisConst.USER_CART_KEY_SUFFIX );
        if(CollectionUtils.isEmpty ( cartInfoList )){
            //缓存中没有,去数据库查询
            cartInfoList = cartInfoMapper.selectList ( new QueryWrapper<CartInfo> ( ).eq ( "user_id" ,userId ) );
        }
        //查实时价格
        cartInfoList.forEach ( cartInfo -> {
            cartInfo.setSkuPrice ( productFeignClient.getPrice ( cartInfo.getSkuId () ) );
        } );
        //排序
        cartInfoList.stream ().sorted ( (CartInfo o1,CartInfo o2)->{
            return o2.getId ().intValue ()-o1.getId ().intValue ();
        } );
        return cartInfoList;
    }

    //封装获取得到userId
    public String getUserId(){
        ServletRequestAttributes requestAttributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes ( );
        HttpServletRequest request = requestAttributes.getRequest ( );
        String userId = AuthContextHolder.getUserId ( request );
        if(StringUtils.isEmpty ( userId )){
           return  userId=AuthContextHolder.getUserTempId ( request );
        }
        return userId;
    }
    //选中或者取消
    @Override
    public void checkCart(Long skuId ,Integer isChecked) {
        String userId=getUserId ();
        CartInfo cartInfo =new CartInfo ();
        cartInfo.setIsChecked ( isChecked );
        cartInfoMapper.update ( cartInfo,new QueryWrapper<CartInfo> (  )
                .eq ( "user_id",userId ).eq ( "sku_id",skuId ) );

    }

    //全选
    @Override
    public void chooseAll(Integer isChecked) {
        String userId=getUserId ();
        CartInfo cartInfo =new CartInfo ();
        cartInfo.setIsChecked ( isChecked );
        cartInfoMapper.update ( cartInfo,new QueryWrapper<CartInfo> (  )
                .eq ( "user_id",userId ));

    }

    //删除被选中的
    @Override
    public void deleteChecked() {
        String userId=getUserId ();
        List<CartInfo> cartInfoList = cartInfoMapper.selectList ( new QueryWrapper<CartInfo> ( )
                .eq ( "user_id" ,userId ).eq ( "is_checked" ,isChecked ) );
        List<String> skuIdList = cartInfoList.stream()
                .map(cartInfo -> cartInfo.getSkuId().toString()).
                        collect(Collectors.toList());
        cartInfoMapper.delete (  new QueryWrapper<CartInfo> (  )
                .eq ( "user_id",userId ).eq ( "is_checked" ,isChecked));
        for (String skuId : skuIdList) {
            redisTemplate.opsForHash().delete(RedisConst.USER_KEY_PREFIX +
                            userId + RedisConst.USER_CART_KEY_SUFFIX,
                    skuId);
        }

    }

    //删除购物车
    @Override
    public void deleteCart(Long skuId) {
        String userId=getUserId ();
        cartInfoMapper.delete (  new QueryWrapper<CartInfo> (  )
                .eq ( "user_id",userId ).eq ( "sku_id" ,skuId));
        redisTemplate.opsForHash().delete(RedisConst.USER_KEY_PREFIX +
                        userId + RedisConst.USER_CART_KEY_SUFFIX,
                skuId.toString ());
    }

    //增加一个
    @Override
    public void addToCart1(Long skuId ,Integer skuNum ,String userId) {
        CartInfo cartInfo = cartInfoMapper.selectOne(new QueryWrapper<CartInfo> ()
                .eq("user_id", userId).eq("sku_id", skuId));
        if (null != cartInfo) {
            //同款 合并数量
            cartInfo.setSkuNum ( cartInfo.getSkuNum ( ) + skuNum );
            cartInfo.setIsChecked ( isChecked );
            //更新
            cartInfoMapper.updateById ( cartInfo );//Canal 同步的Redis缓存中
            ThreadUtil.sleep (1000);
        }
    }

    //查询选中
    @Override
    public List<CartInfo> findChecked(String userId) {
        //方法1:直接查数据库
//        List<CartInfo> cartInfoList = cartInfoMapper.selectList ( new QueryWrapper<CartInfo> ( )
//                .eq ( "user_id" ,userId ).eq ( "is_checked" ,isChecked ) );
        //方法二:先走缓存,缓存中没有,在查询数据库
        List<CartInfo> cartInfoList = getCartInfoList ( userId );
        cartInfoList = cartInfoList.stream ( ).filter (
                cartInfo -> cartInfo.getIsChecked ( ).equals ( isChecked )
         ).collect ( Collectors.toList ( ) );

        return cartInfoList;
    }

}
